home *** CD-ROM | disk | FTP | other *** search
- /*
- File: Mysprintf.c
-
- Copyright: © 1997-1998 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #pragma segment AppSeg
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __STDARG__
- #include <stdarg.h>
- #endif
-
- #ifndef __STDLIB__
- #include <StdLib.h>
- #endif
-
- #ifndef __FP__
- #include <fp.h>
- #endif
-
- #ifndef __MYSPRINTF__
- #include "Mysprintf.h"
- #endif
-
- // local prototypes
- void Calc_Widths(UInt32* Lwidth, UInt32 Lplace, UInt32* Rwidth, UInt32 Rplace);
- void PrintString(StringPtr* s, StringPtr sval, Boolean LeftJustified, UInt32 Lwidth, UInt32 Rwidth);
- StringPtr numToBase(StringPtr destStr, UInt8 filler, UInt32 base, UInt32 digits,UInt32 value);
-
- #define MaxBase 16
- #define MaxIndex 32
-
- #undef NULL
- #define NULL 0L
-
-
- // ********************************************************************************
- // * Myssprintf() *
- // ********************************************************************************
- void Mysprintf(StringPtr s, StringPtr fmt,...)
- {
- va_list ap; // points to each unnamed arg in turn
- UInt8 *p, *sval;
- UInt32 ival;
- double dval;
- float_t fval;
- UInt32 power;
- Boolean conversion;
- Boolean Lspace,ShowVal,LeftJustified;
- UInt8 c,filler;
- UInt32 Lwidth,Rwidth;
- UInt32 Lplace,Rplace,width;
- Str255 tStr;
- StringPtr aChar;
-
- va_start(ap,fmt); // make ap point to 1st unnamed arg
- conversion = false;
- for (p = fmt; *p; p++)
- {
- if (*p != '%' && !conversion)
- {
- *s++ = *p;
- continue;
- }
- if (*p == '%' && !conversion)
- {
- conversion = true;
- p++; // point to conversion char
- Lwidth = NULL;
- Lplace = NULL;
- Rwidth = NULL;
- Rplace = NULL;
- Lspace = true; // calculate Lspace 1st
- ShowVal = false;
- LeftJustified = false;
- filler = ' '; // default to blank unless otherwise specified
- }
- c = *p;
- switch(c)
- {
- case '%': // just a % char
- *s++ = '%';
- conversion = false;
- break;
- case 'd':
- Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
- ival = va_arg(ap,int);
- numToBase(tStr,filler,10,Lwidth,ival);
- PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
- conversion = false;
- break;
- case 'f':
- Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
- fval = va_arg(ap, float_t);
- ival = (UInt32) fval; // during translation, the mantissa should be dropped
- // aChar = numToBase(tStr,filler,10,Lwidth,ival);
- aChar = numToBase(tStr,filler,10,0,ival); // experimenting w/ 0 width, so we get all digits
- *aChar++ = '.'; // insert decimal point
- {
- UInt32 tindex = Rwidth;
- power = 1;
- while (tindex)
- {
- power *= 10;
- tindex--;
- }
- }
- dval = (fval-ival) * power;
- numToBase(aChar,filler,10,Rwidth,dval);
- PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
- conversion = false;
- break;
- case 's':
- Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
- sval = va_arg(ap, StringPtr);
- PrintString(&s, sval, LeftJustified, Lwidth, Rwidth);
- conversion = false;
- break;
- case 'o': // octal
- Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
- if (ShowVal)
- {
- *s++ = '0';
- }
- ival = va_arg(ap,int);
- numToBase(tStr,filler,8,Lwidth,ival);
- PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
- conversion = false;
- break;
- case 'h': // h, short
- case 'l': // ell, long
- break;
- case 'x': // hex lower
- case 'X': // hex upper
- Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
- if (ShowVal)
- {
- if (c == 'x')
- BlockMove("0x",s,2);
- else
- BlockMove("0X",s,2);
-
- s+= 2;
- }
- ival = va_arg(ap,int);
- numToBase(tStr,filler,16,Lwidth,ival);
- PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
- conversion = false;
- break;
- case 'b': // binary
- Calc_Widths(&Lwidth,Lplace,&Rwidth,Rplace);
- if (ShowVal)
- {
- BlockMove("0b",s,2);
- s+= 2;
- }
- ival = va_arg(ap,int);
- numToBase(tStr,filler,2,Lwidth,ival);
- PrintString(&s, tStr, LeftJustified, Lwidth, Rwidth);
- conversion = false;
- break;
- case '0':
- if (Lplace == NULL)
- filler = '0';
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (Lspace)
- {
- Lwidth = Lwidth << 8;
- Lplace++;
- Lwidth += c - '0';
- }
- else
- {
- Rwidth = Rwidth << 8;
- Rplace++;
- Rwidth += c - '0';
- }
- break;
- case '.':
- Lspace = false;
- break;
- case '#':
- ShowVal = true;
- break;
- case '-':
- LeftJustified = true;
- break;
- case '+':
- break;
- case ' ':
- if (Lspace)
- {
- filler = ' ';
- }
- break;
- case '*':
- width = va_arg(ap,int); // get width
- if (Lspace)
- {
- Lwidth = width;
- Lplace = NULL;
- }
- else
- {
- Rwidth = width;
- Rplace = NULL;
- }
- break;
- default:
- *s++ = *p;
- break;
- }
- }
- va_end(ap); // clean up when done
- *s = 0;
- }
-
-
- // ********************************************************************************
- // * Calc_Widths()
- // ********************************************************************************
- void Calc_Widths(UInt32* Lwidth,UInt32 Lplace, UInt32* Rwidth, UInt32 Rplace)
- {
- UInt32 x,value,base;
- Ptr width;
-
- if (Lplace)
- {
- width = (Ptr) Lwidth+3;
- for(x=0,value=0,base=1;x<Lplace;x++)
- {
- value += (*width) * base;
- base *= 10;
- width--;
- }
- *Lwidth = value;
- }
-
- if (Rplace)
- {
- width = (Ptr) Rwidth+3;
- for(x=0,value=0,base=1;x<Rplace;x++)
- {
- value += (*width) * base;
- base *= 10;
- width--;
- }
- *Rwidth = value;
- }
- }
-
-
- // ********************************************************************************
- // * Calc_Widths()
- // *
- // * PrintString
- // *
- // * if (LeftJustified)
- // * "|xxxxx |"
- // * else
- // * "| xxxxx|"
- // *
- // * Lwidth = min # of chars
- // * Rwidth = max # of chars
- // ********************************************************************************
- void PrintString(StringPtr* str, StringPtr sval, Boolean LeftJustified, UInt32 Lwidth, UInt32 Rwidth)
- {
- StringPtr s = *str;
- UInt32 valid;
- UInt32 validR = NULL;
-
- valid = Lwidth;
- if (!valid)
- valid = 255; // if NULL, default to max
-
- if (LeftJustified)
- { //
- // output data 1st, then fill
- //
- if (Rwidth)
- {
- validR = Rwidth;
- }
- else
- {
- validR = valid;
- }
-
- while (validR && *sval)
- {
- *s++ = *sval;
- validR--;
- valid--;
- sval++;
- }
-
- while (valid)
- { //
- // we need to fill in the rest
- //
- *s++ = ' ';
- valid--;
- }
- }
- else
- { //
- // output filler 1st
- //
- if (Rwidth)
- {
- validR = valid - Rwidth;
- }
- else
- {
- valid = 255; // max allowed
- }
-
- while (validR)
- { //
- // we need to fill in the rest
- //
- *s++ = ' ';
- validR--;
- valid--;
- }
-
- //
- // output data 2nd
- //
- while (*sval && valid)
- {
- *s++ = *sval;
- valid--;
- sval++;
- }
- }
-
- *str = s;
- }
-
-
- // ********************************************************************************
- // * StringPtr numToBase (Ptr destStr, char filler, int base, int digits, unsigned int value)
- // * inputs:
- // * destStr : destination string
- // * filler : leading space filler, usually '0'
- // * base : conversion base, 2=binary,8=octal,10=decimal,16=hex
- // * digits : # of digits to display
- // * value : number to convert
- // * output:
- // * the cstring representation of value will be moved to the location pointed to by "destStr"
- // * return ptr to last char we store a null to
- // ********************************************************************************
- StringPtr numToBase(StringPtr destStr, UInt8 filler, UInt32 base, UInt32 digits, UInt32 value)
- {
- UInt8 hex[16];
- UInt8 tStr[MaxIndex+1];
- UInt8* aStr;
- UInt32 index,lastIndex;
- UInt8 digit,sign;
-
- // init hex array
- for (index = 0, digit = '0'; index < 16; )
- {
- hex[index] = digit;
- digit++;
- index++;
- if (index == 10)
- digit = 'A';
- }
-
- sign = 0;
- if (base == 10) // special decimal handling
- {
- if (value &0x80000000)
- {
- value = abs(value);
- sign = '-'; // automatically insert the '-' value
- }
- }
- index = MaxIndex-1;
- tStr[MaxIndex] = 0; // terminate string
-
- do {
- digit = (value % base) & 0x0F;
- tStr[index] = hex[digit];
- value -= digit;
- if (value)
- {
- value /= base;
- }
- index--;
- }
- while (value);
-
- if (sign)
- {
- tStr[index] = sign;
- index--;
- }
- lastIndex = index+1;
-
- while(index!=-1)
- {
- tStr[index] = filler;
- index--;
- }
- if (digits)
- {
- aStr = tStr + (MaxIndex-digits);
- }
- else
- {
- aStr = tStr+lastIndex;
- }
-
- do {
- *destStr++ = *aStr++; // copy aStr to destStr
- }
- while (*aStr);
-
- *destStr = 0; // make sure we terminate the destination
-
- return (destStr);
- }
-